package com.tian.manager.config;

import com.tian.manager.realm.CustomRealm;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import shiro.CustomSessionManager;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfiguration {


    // 配置自定义的Realm
    @Bean
    public CustomRealm getRealm(){
        return new CustomRealm();
    }



    // 配置安全管理器
    @Bean
    public SecurityManager securityManager(CustomRealm realm){
        // 使用默认的安全管理器
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(realm);
        // 将自定义的会话管理器注册到安全管理器中
        securityManager.setSessionManager(defaultWebSessionManager());
        // 将自定义的redis管理器注册到安全管理器中
        securityManager.setCacheManager(cacheManager());

        // 讲自定义的realm交给安全管理器同意调度管理
        securityManager.setRealm(realm);
        return securityManager;
    }

    //Filter工厂，设置对应的过滤条件和跳转条件
    @Bean
    public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
        //1.创建shiro过滤器工厂
        ShiroFilterFactoryBean filterFactory = new ShiroFilterFactoryBean();
        //2.设置安全管理器
        filterFactory.setSecurityManager(securityManager);
        //3.通用配置（配置登录页面，登录成功页面，验证未成功页面）
        filterFactory.setLoginUrl("/login");// 跳转url地址
        filterFactory.setUnauthorizedUrl("/login");// 未授权的uri
        //4.配置过滤器集合
        /**
        * key ：访问连接
        *     支持通配符的形式
        * value：过滤器类型
        *     shiro常用过滤器
        *         anno   ：匿名访问（表明此链接所有人可以访问）
        *         authc   ：认证后访问（表明此链接需登录认证成功之后可以访问）
        */
        Map<String,String> filterMap = new LinkedHashMap<String,String>();
        // 配置不会被拦截的链接 顺序判断
        // todo
        filterMap.put("/**", "anon");
        // filterMap.put("/user/home", "anon");
        // filterMap.put("/user/**", "authc");
        //5.设置过滤器
        filterFactory.setFilterChainDefinitionMap(filterMap);
        return filterFactory;
        }

    @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private int port;

    /**
     *      1. redis的控制器，操作redis
     *
     */
    public RedisManager redisManager(){
        RedisManager redisManager = new RedisManager();
        redisManager.setHost(host);
        redisManager.setPort(port);
        return redisManager;

    }


    /**
     *      2. sessionDao
     */
    public RedisSessionDAO redisSessionDAO(){
        RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
        redisSessionDAO.setRedisManager(redisManager());
        return redisSessionDAO;
    }

    /**
     *      3. 会话管理器
     */
    public DefaultWebSessionManager defaultWebSessionManager(){
        CustomSessionManager sessionManager = new CustomSessionManager();
        sessionManager.setSessionDAO(redisSessionDAO());
//        // 禁用cookie
//        sessionManager.setSessionIdCookieEnabled(false);
        // 禁用url重写 url: jsessionid=id
        sessionManager.setSessionIdUrlRewritingEnabled(false);

        return sessionManager;
    }

    /**
     *      4. 缓存管理器
     */
    public RedisCacheManager cacheManager(){
        RedisCacheManager redisCacheManager = new RedisCacheManager();
        redisCacheManager.setRedisManager(redisManager());
        return redisCacheManager;
    }


    //配置shiro注解支持
    @Bean
    public AuthorizationAttributeSourceAdvisor
    authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new
                AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }
}
